{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `tfplot.contrib`: Some pre-defined plot ops"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `tfplot.contrib` package contains some off-the-shelf functions for defining plotting operations.\n",
    "This package provides some off-the-shelf functions that could be useful widely across many typical use cases.\n",
    "\n",
    "Unfortunately, it may not provide super flexible and fine-grained customization points beyond the current parameters. If it does not fit what you want to get, then consider designing your own plotting functions using `tfplot.autowrap`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "nbsphinx": "hidden"
   },
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "nbsphinx": "hidden"
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from matplotlib import rcParams, rc\n",
    "from IPython.core.pylabtools import figsize\n",
    "figsize(5, 4)\n",
    "\n",
    "%config InlineBackend.figure_format = 'retina'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbsphinx": "hidden"
   },
   "source": [
    "## Setup (Skip this!)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "nbsphinx": "hidden"
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "\n",
    "sess = tf.InteractiveSession()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "nbsphinx": "hidden"
   },
   "outputs": [],
   "source": [
    "from PIL import Image\n",
    "def execute_op_as_image(op):\n",
    "    \"\"\"\n",
    "    Evaluate the given `op` and return the content PNG image as `PIL.Image`.\n",
    "    \n",
    "    - If op is a plot op (e.g. RGBA Tensor) the image or\n",
    "      a list of images will be returned\n",
    "    - If op is summary proto (i.e. `op` was a summary op),\n",
    "      the image content will be extracted from the proto object.\n",
    "    \"\"\"\n",
    "    print (\"Executing: \" + str(op))\n",
    "    ret = sess.run(op)\n",
    "    plt.close()\n",
    "\n",
    "    if isinstance(ret, np.ndarray):\n",
    "        if len(ret.shape) == 3:\n",
    "            # single image\n",
    "            return Image.fromarray(ret)\n",
    "        elif len(ret.shape) == 4:\n",
    "            return [Image.fromarray(r) for r in ret]\n",
    "        else:\n",
    "            raise ValueError(\"Invalid rank : %d\" % len(ret.shape))            \n",
    "            \n",
    "    elif isinstance(ret, (str, bytes)):\n",
    "        from io import BytesIO\n",
    "        s = tf.Summary()\n",
    "        s.ParseFromString(ret)\n",
    "        ims = []\n",
    "        for i in range(len(s.value)):\n",
    "            png_string = s.value[i].image.encoded_image_string\n",
    "            im = Image.open(BytesIO(png_string))\n",
    "            ims.append(im)\n",
    "        plt.close()\n",
    "        if len(ims) == 1: return ims[0]\n",
    "        else: return ims\n",
    "        \n",
    "    else:\n",
    "        raise TypeError(\"Unknown type: \" + str(ret))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "nbsphinx": "hidden"
   },
   "outputs": [],
   "source": [
    "def fake_attention():\n",
    "    import scipy.ndimage\n",
    "    attention = np.zeros([16, 16], dtype=np.float32)\n",
    "    attention[(11, 8)] = 1.0\n",
    "    attention[(9, 9)] = 1.0\n",
    "    attention = scipy.ndimage.filters.gaussian_filter(attention, sigma=1.5)\n",
    "    return attention\n",
    "\n",
    "import scipy\n",
    "sample_image = scipy.misc.face()\n",
    "attention_map = fake_attention()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "batch                Make an autowrapped plot function (... -> RGBA tf.Tensor) work in a batch\n",
      "probmap              Display a heatmap in color. The resulting op will be a RGBA image Tensor.\n",
      "probmap_simple       Display a heatmap in color, but only displays the image content.\n"
     ]
    }
   ],
   "source": [
    "import tfplot.contrib\n",
    "\n",
    "for fn in sorted(tfplot.contrib.__all__):\n",
    "    print(\"%-20s\" % fn, tfplot.contrib.__dict__[fn].__doc__.split('\\n')[1].strip())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## probmap"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For example, `probmap` and `probmap_simple` create an image Tensor that visualizes a probability map:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tensor(\"attention_op:0\", shape=(16, 16), dtype=float32)\n",
      "Executing: Tensor(\"probmap:0\", shape=(?, ?, 4), dtype=uint8)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGBA size=288x216 at 0x108C51EF0>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "attention_op = tf.constant(attention_map, name=\"attention_op\")\n",
    "print(attention_op)\n",
    "\n",
    "op = tfplot.contrib.probmap(attention_map, figsize=(4, 3))\n",
    "execute_op_as_image(op)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Executing: Tensor(\"probmap_1:0\", shape=(?, ?, 4), dtype=uint8)\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAANgAAADYCAYAAACJIC3tAAADWElEQVR4nO3coW5VURRF0QsBgQCB\nQSDgT/lVRBGQUEEFok1A1668eVseY/idc/uamWN2zovj+PLnABIvn/oD4JoJDEICg5DAICQwCAkM\nQgKDkMAgJDAICQxCAoOQwCAkMAgJDEICg5DAICQwCAkMQgKDkMAgJDAICQxCAoOQwCAkMAgJDEIC\ng5DAICQwCAkMQgKDkMAgJDAICQxCAoOQwCAkMAgJDEICg5DAICQwCAkMQgKDkMAgJDAICQxCAoOQ\nwCAkMAgJDEICg5DAICQwCAkMQgKDkMAgJDAICQxCAoOQwCAkMAgJDEICg5DAICQwCAkMQgKDkMAg\nJDAICQxCAoOQwCAkMAgJDEICg5DAICQwCAkMQgKDkMAg9OqpP+D/9XqcO/Nf9nDiWfcnnnUeNxiE\nBAYhgUFIYBASGIQEBiGBQUhgEBIYhAQGIYFBSGAQsux7Ecvi7pvxrLfDzLpYvCzg3o1nLZ7/grAb\nDEICg5DAICQwCAkMQgKDkMAgJDAICQxCAoOQwCAkMAgJDEK26S9i+Rnfj2d9HmbWzf3bYeZmPGvZ\njLdND/81gUFIYBASGIQEBiGBQUhgEBIYhAQGIYFBSGAQEhiELPs+sj4x/W6Y+Tie9WmYWb7vOI7j\n6zDzczzrOrnBICQwCAkMQgKDkMAgJDAICQxCAoOQwCAkMAgJDEICg5DAIGSb/pH151iepl6fzv4w\nzp3l4ak/4Flxg0FIYBASGIQEBiGBQUhgEBIYhAQGIYFBSGAQEhiEBAYhy74XcebP+HuY+TWedTvM\nLN93HNe6JOwGg5DAICQwCAkMQgKDkMAgJDAICQxCAoOQwCAkMAgJDEICg5Bt+otYNsh/jGctW+fr\nhvu3YWbd3L8f5543NxiEBAYhgUFIYBASGIQEBiGBQUhgEBIYhAQGIYFBSGAQsuz7yPp8890wczOe\n9X2YWRdpl7/rOp/AXrnBICQwCAkMQgKDkMAgJDAICQxCAoOQwCAkMAgJDEICg5DAIGSb/pEzn29e\nn7M+81+2bMZf5xPYKzcYhAQGIYFBSGAQEhiEBAYhgUFIYBASGIQEBiGBQUhgELLsexFnLrhapv2X\nuMEgJDAICQxCAoOQwCAkMAgJDEICg5DAICQwCAkMQgKDkMAg9BeKIyepB5PbHwAAAABJRU5ErkJg\ngg==\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGBA size=216x216 at 0x128049B00>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "op = tfplot.contrib.probmap_simple(attention_map, figsize=(3, 3),\n",
    "                                   vmin=0, vmax=1)\n",
    "execute_op_as_image(op)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Auto-batch mode (`tfplot.contrib.batch`)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In many cases, we may want to make plotting operations behave in a batch manner. You can use `tfplot.contrib.batch` to make those functions work in a batch mode:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tensor(\"batch_tensor:0\", shape=(5, 5, 5), dtype=float64)\n",
      "Executing: Tensor(\"probmap_2/PlotImages:0\", shape=(5, ?, ?, 4), dtype=uint8)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nRK5CYII=\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGBA size=1080x144 at 0x128084A58>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# batch version\n",
    "N = 5\n",
    "p = np.zeros([N, N, N])\n",
    "for i in range(N):\n",
    "    p[i, i, i] = 1.0\n",
    "\n",
    "p = tf.constant(p, name=\"batch_tensor\"); print(p)                      # (batch_size, 5, 5)\n",
    "op = tfplot.contrib.batch(tfplot.contrib.probmap)(p, figsize=(3, 2))   # (batch_size, H, W, 4)\n",
    "\n",
    "results = execute_op_as_image(op)      # list of N images\n",
    "Image.fromarray(np.hstack([np.asarray(im) for im in results]))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
